package com.choosefine.paycenter.settlement.handler;

import com.choosefine.paycenter.account.dto.AccountWdDto;
import com.choosefine.paycenter.account.model.Account;
import com.choosefine.paycenter.account.model.AccountBankcard;
import com.choosefine.paycenter.account.model.AccountBill;
import com.choosefine.paycenter.account.service.AccountBankcardService;
import com.choosefine.paycenter.account.service.AccountBillService;
import com.choosefine.paycenter.account.service.AccountService;
import com.choosefine.paycenter.common.enums.*;
import com.choosefine.paycenter.common.utils.PaycenterStringUtils;
import com.choosefine.paycenter.common.utils.SerialNumberUtils;
import com.choosefine.paycenter.pay.service.ChannelService;
import com.choosefine.paycenter.pay.service.PayVerifyService;
import com.choosefine.paycenter.settlement.dto.WithdrawDTO;
import com.choosefine.paycenter.settlement.model.Withdraw;
import com.choosefine.paycenter.settlement.service.WithdrawBankService;
import com.choosefine.paycenter.settlement.service.impl.WithdrawServiceImpl;
import com.choosefine.paycenter.settlement.vo.WithDrawVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;

/**
 * @author 潘钱钦（qianqinpan@outlook.com）
 * @create 2017-05-05 15:51
 **/
@Component
public abstract class AbstractWithdrawHandler implements WithdrawHandler{
    private final double bigAmount = 50000.00;

    @Autowired
    private AccountService accountService;

    @Autowired
    private AccountBankcardService accountBankcardService;

    @Autowired
    SerialNumberUtils serialNumberUtils;

    @Autowired
    private PayVerifyService payVerifyService;

    @Autowired
    WithdrawServiceImpl withdrawService;

    @Autowired
    ChannelService channelService;

    @Autowired
    AccountBillService accountBillService;

    protected WithdrawBankService withdrawBankService;

    WithDrawVo withDrawVo = null;

    Withdraw withdraw = null;

    AccountWdDto accountDTO = null;

    @Transactional(rollbackFor = Exception.class)
    public WithDrawVo buildWithDraw(WithdrawDTO withdrawDTO, String userCode) {
        //一开始要判断交易账号是否与登陆账号一致
        accountService.checkUserIsRight(withdrawDTO.getAccountId(), userCode);
        //首先判断该用户是不是已经提现且上一笔提现未完成
        withdrawService.checkHasWaittingWithdraw(withdrawDTO.getAccountId());
        //首先检查账户是否已经被冻结
        accountService.checkAccountIsLockedOrBlocked(withdrawDTO.getAccountId());
        //校验用户的余额是否充足
        Double withDrawAmount = Double.valueOf(withdrawDTO.getAmount());
        accountService.checkBalanceIsEnough(withdrawDTO.getAccountId(), BigDecimal.valueOf(withDrawAmount));

        //查询提现账户信息
        Account account = accountService.findByUserCode(userCode);
        //查询提现的银行卡信息
        AccountBankcard accountBankcard = accountBankcardService.findAccountBankById(withdrawDTO.getBankCardId());//查询提现卡的卡号
        String bankCardNum = accountBankcard.getBankcardNo();
        //现已经校验在添加银行卡的时候，必须传bankCode
        String bankCode= accountBankcard.getBankCode();
//        if (withDrawAmount.doubleValue() >= bigAmount) {//如果提现金额超过了5w的其它逻辑
//            // TODO: 2017/5/5 大额提现的逻辑
//        }
        //校验支付密码是否正确
        payVerifyService.checkPayPass(withdrawDTO.getAccountId(), withdrawDTO.getPassword());
        // 冻结提现的金额，更新账户余额
        BigDecimal freezeBalance = new BigDecimal(withDrawAmount);
        BigDecimal balance = account.getBalance();
        BigDecimal availableBalance=balance.subtract(freezeBalance);
        accountDTO = new AccountWdDto();
        accountDTO.setAccountId(withdrawDTO.getAccountId());
        accountDTO.setAvailableBalance(availableBalance);
        accountDTO.setBalance(balance);
        accountDTO.setFreezeBalance(freezeBalance);
        accountDTO.setUserCode(userCode);
        accountService.updateAccountBalanceBeforWithDraw(accountDTO);
        //生成提现请求对象
        withDrawVo = new WithDrawVo();
        withDrawVo.setAmount(withdrawDTO.getAmount());
        withDrawVo.setBankTypeName(withdrawDTO.getUbankName());
        //注意：这里如果账户名称如果跟开卡的时候的账户名称不符就会提现失败
        withDrawVo.setWithDrawRealName(accountBankcard.getBankAccountName());
        withDrawVo.setWithDrawBankCardNum(bankCardNum);
        withDrawVo.setWithDrawSn(serialNumberUtils.getWithdrawSn());
        withDrawVo.setRequestSn(serialNumberUtils.getBankRequestSn());
        withDrawVo.setWithdrawBankCode(bankCode);
        withDrawVo.setBankUnion(withdrawDTO.getBankUnion());
        //插入提现记录
        withdraw = new Withdraw();
        withdraw.setAccountBankcardId(withdrawDTO.getBankCardId());
        withdraw.setAccountId(withdrawDTO.getAccountId());
        withdraw.setAccountRealName(account.getRealName());
        withdraw.setAmount(new BigDecimal(withDrawAmount));
        withdraw.setBankcardName(accountBankcard.getBankName());
        withdraw.setBankcardNo(bankCardNum);
        withdraw.setStatus(WithdrawStatus.WAITING);
        withdraw.setWSn(withDrawVo.getWithDrawSn());
        withdraw.setBankRequestSn(withDrawVo.getRequestSn());
        withdraw.setWPayBankCode("");
        withdraw.setOperName(withdrawDTO.getOperName());
        withdrawService.addWithdraw(withdraw);
        //记录账单
        AccountBill accountBill=new AccountBill();
        accountBill.setBizzSys(BizzSys.SELF);
        accountBill.setBizzSn(null);
        accountBill.setAmount(withdraw.getAmount());
        accountBill.setFundFlow(FundFlow.OUT);
        accountBill.setMainAccountId(withdraw.getAccountId());
        accountBill.setMainAccountRealName(withdraw.getAccountRealName());
        accountBill.setMainAccountUserCode(userCode);
        accountBill.setMainAccountMobile(PaycenterStringUtils.getInstance().hiddenByChar(account.getMobile(),3,6,'*'));
        accountBill.setBankName(accountBankcard.getBankName());
        accountBill.setBankcardNo(bankCardNum.substring(bankCardNum.length()-4));
        accountBill.setBankcardDigits(bankCardNum.length()+"");
        accountBill.setOperName(withdraw.getOperName());
        //记录提现的银行卡的银行logo
        accountBill.setImg(channelService.findLogoByBankCode(accountBankcard.getBankCode()));
        accountBill.setStatus(AccountBillStatus.PROCESSING);
        accountBill.setTradeMemo("提现");
        accountBill.setOrderSn(withdraw.getWSn());
        accountBill.setTradeType(TradeType.WITHDRAW);
        accountBillService.recordAccountBill(accountBill);
        return withDrawVo;
    }
}
